﻿using Kaskelot.SP.Core;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Utilities;
using Stockholm.SOA.Kaskelot.WCF.DataContracts;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Web;
using System.Xml;

namespace Kaskelot.SP.Services
{
	public class IntegrationService
	{
		#region Utility functions
		private Stream ZipFolder(SPFolder folder)
		{
			Stream s = new MemoryStream();

			ZipFileBuilder builder = new ZipFileBuilder(s);

			ZipFolderRecursive(builder, folder, folder.Name + "/");

			builder.Finish();

			return s;
		}

		private void ZipFolderRecursive(ZipFileBuilder builder, SPFolder folder, string path)
		{
			foreach (SPFile file in folder.Files)
			{
				builder.Add(path + file.Name, file.OpenBinaryStream());
			}

			foreach (SPFolder subfolder in folder.SubFolders)
			{
				builder.AddDirectory(path + subfolder.Name);

				ZipFolderRecursive(builder, subfolder, path + subfolder.Name + "/");
			}
		}

		private string HashSPFile(SPFile file)
		{
			if (file == null || !file.Exists)
				throw new ArgumentException("Specifierad fil existerar inte.");

			using (SHA1Managed sha1 = new SHA1Managed())
			{
				byte[] hash = sha1.ComputeHash(file.OpenBinaryStream());
				StringBuilder formatted = new StringBuilder(2 * hash.Length);
				foreach (byte b in hash)
				{
					formatted.AppendFormat("{0:X2}", b);
				}

				return formatted.ToString();
			}
		}

		private string SaveIntegration(byte[] bytes, string filename, SPFolder folder)
		{
			string s = string.Empty;
			return SaveIntegration(bytes, filename, folder, out s);
		}

		private string SaveIntegration(byte[] bytes, string filename, SPFolder folder, out string hash)
		{
			SPFile file = folder.Files.Add(filename, bytes, true);
			hash = HashSPFile(file);
			return file.Url;
		}
		#endregion

		#region LISA
		private string CreateLISAPersonFil(SPFolder folder)
		{
			MemoryStream ms = new MemoryStream();
			string filename = "LISAPersoner.txt";
			Encoding enc = Encoding.GetEncoding("ISO-8859-1");

			using (AdminService svc = new AdminService())
			{
				IEnumerable<PersonData> personer = svc.GetPersonData();
				personer = personer.GroupBy(x => x.Personnummer).Select(x => x.First());
				personer = personer.OrderBy(p => p.Personnummer);

				foreach (PersonData lp in personer)
				{
					string s = lp.PersonFilRad + "\r\n";
					ms.Write(enc.GetBytes(s), 0, s.Length);
				}
			}

			byte[] bytes = ms.GetBuffer();
			bytes = bytes.TakeWhile(x => x != 0).ToArray();
			bytes = bytes.Take(bytes.Length - 2).ToArray();
			return SaveIntegration(bytes, filename, folder);
		}

		private string CreateLISATransaktionsFil(SPFolder folder)
		{
			MemoryStream ms = new MemoryStream();
			string filename = "LISATransaktioner.txt";
			Encoding enc = Encoding.GetEncoding("ISO-8859-1");

			using (AdminService svc = new AdminService())
			{
				IEnumerable<PersonData> personer = svc.GetPersonData();

				foreach (PersonData lp in personer)
				{
					string s = lp.LonFilRad + "\r\n";
					ms.Write(enc.GetBytes(s), 0, s.Length);
				}
			}

			byte[] bytes = ms.GetBuffer();
			bytes = bytes.TakeWhile(x => x != 0).ToArray();
			bytes = bytes.Take(bytes.Length - 2).ToArray();
			return SaveIntegration(bytes, filename, folder);
		}

		public string CreateLISAFiler()
		{
			string url = null;
			Guid siteId = SPContext.Current.Site.ID;

			SPSecurity.RunWithElevatedPrivileges(delegate()
			{
				using (SPSite site = new SPSite(siteId))
				{
					bool oldAllowUnsafeUpdates = site.RootWeb.AllowUnsafeUpdates;

					try
					{
						site.RootWeb.AllowUnsafeUpdates = true;

						SPFolder folder = new DocumentService().GetLISAFolder(site);

						CreateLISAPersonFil(folder);
						CreateLISATransaktionsFil(folder);

						Stream zipStream = ZipFolder(folder);

						SPFile file = folder.ParentFolder.Files.Add("LISA.zip", zipStream, true);

						url = file.Url;
					}
					finally
					{
						site.RootWeb.AllowUnsafeUpdates = oldAllowUnsafeUpdates;
					}
				}

			});

			return url;
		}
		#endregion

		#region Skatteverket
		private string CreateSkatteverketFil(SPFolder folder)
		{
			MemoryStream ms = new MemoryStream();
			string filename = Constants.Integrationer.SkatteverketFilnamn;
			Encoding enc = Encoding.GetEncoding("ISO-8859-1");

			using (AdminService svc = new AdminService())
			{
				IEnumerable<string> personer = svc.GetPersonnummerList();

				string start = String.Empty, slut = String.Empty;

				start += "#INFO_START\r\n";
				start += "#FILTYP INDATAFIL\r\n";
				start += "#BESTÄLLNINGSID 00002903-FO01-0040\r\n";
				start += "#BESTÄLLNINGSTYP URVAL\r\n";
				start += "#NAMN_INFIL " + filename + "\r\n";
				start += "#GILTIG_TOM\r\n";
				start += "#INFO_SLUT\r\n";
				start += "#DATA_START\r\n";

				slut += "#DATA_SLUT\r\n";
				slut += "#AVST_START\r\n";
				slut += "#ANTAL_POSTER " + personer.Count().ToString().PadLeft(8, '0') + "\r\n";
				slut += "#AVST_SLUT\r\n";
				slut += "#FIL_SLUT";

				ms.Write(enc.GetBytes(start), 0, start.Length);

				foreach (string pn in personer)
				{
					string s = "#PNR " + pn.Replace("-", "") + "\r\n";
					ms.Write(enc.GetBytes(s), 0, s.Length);
				}

				ms.Write(enc.GetBytes(slut), 0, slut.Length);
			}

			byte[] bytes = ms.GetBuffer();
			bytes = bytes.TakeWhile(x => x != 0).ToArray();
			return SaveIntegration(bytes, filename, folder);
		}

		private string CreateSkatteverketInfoFil(SPFolder folder)
		{
			MemoryStream ms = new MemoryStream();
			string filename = "INFO.NAV";
			Encoding enc = Encoding.GetEncoding("ISO-8859-1");

			using (AdminService svc = new AdminService())
			{
				string text = String.Empty;

				text += "#MEDIELEV_START\r\n";
				text += "#TECKENPROV ÅÄÖÜåäöüÉé#_@\r\n";
				text += "#ORGNR 212000-0142\r\n";
				text += "#NAMN Valnämndens kansli\r\n";
				text += "#ADRESS Ragnar Östbergs Plan 1\r\n";
				text += "#POSTNR 10535\r\n";
				text += "#POSTORT Stockholm\r\n";
				text += "#MEDIELEV_SLUT\r\n";
				text += "#DATABESKRIVNING_START\r\n";
				text += "#PRODUKT NAVET\r\n";
				text += "#FILNAMN " + Constants.Integrationer.SkatteverketFilnamn + "\r\n";
				text += "#DATABESKRIVNING SLUT";

				ms.Write(enc.GetBytes(text), 0, text.Length);
			}

			byte[] bytes = ms.GetBuffer();
			bytes = bytes.TakeWhile(x => x != 0).ToArray();
			return SaveIntegration(bytes, filename, folder);
		}

		public string CreateSkatteverketFiler()
		{
			string url = null;
			Guid siteId = SPContext.Current.Site.ID;

			SPSecurity.RunWithElevatedPrivileges(delegate()
			{
				using (SPSite site = new SPSite(siteId))
				{
					bool oldAllowUnsafeUpdates = site.RootWeb.AllowUnsafeUpdates;

					try
					{
						site.RootWeb.AllowUnsafeUpdates = true;

						SPFolder folder = new DocumentService().GetSkatteverketFolder(site);

						CreateSkatteverketFil(folder);
						CreateSkatteverketInfoFil(folder);

						Stream zipStream = ZipFolder(folder);

						SPFile file = folder.ParentFolder.Files.Add("Skatteverket.zip", zipStream, true);

						url = file.Url;
					}
					finally
					{
						site.RootWeb.AllowUnsafeUpdates = oldAllowUnsafeUpdates;
					}
				}
			});

			return url;
		}

		public void ImporteraSkatteverketFil(Stream stream)
		{
			Encoding enc = Encoding.GetEncoding("ISO-8859-1");
			StringBuilder sb = new StringBuilder();

			bool cont = true;
			while (cont)
			{
				int val = stream.ReadByte();

				if (val != -1)
					sb.Append(enc.GetChars(new byte[] { (byte)val }));
				else
					cont = false;
			}

			string fil = sb.ToString();

			string[] poster = fil.Split(new string[] { "#POST_START" }, StringSplitOptions.None);

			IList<string> personnummerList = new List<string>();
			foreach (string post in poster)
			{
				string pnr = post.Substring(post.IndexOf("01001") + 6, 12).Insert(8, "-");
				if (pnr.IsValidPersNr())
					personnummerList.Add(pnr);
			}

			using (PersonService svc = new PersonService())
			{
				IList<Person> personer = svc.GetPersonListByPersonnummer(personnummerList);

				foreach (string post in poster)
				{
					string personnummer = post.Substring(post.IndexOf("01001") + 6, 12).Insert(8, "-");

					if (!personnummer.IsValidPersNr())
						continue;

					Person p = personer.FirstOrDefault(x => x.Personnummer == personnummer);

					if (p != null)
					{
						int index = post.IndexOf("01006");
						if (index != -1)
						{
							p.Inaktiv = true;
							#region Anledning
							switch (post.Substring(index + 6, 2))
							{
								case "AV":
									p.Fritext = p.Fritext + "\r\nPerson inaktiverad vid datatvätt hos Skatteverket med angiven anledning: Avliden";
									break;
								case "UV":
									p.Fritext = p.Fritext + "\r\nPerson inaktiverad vid datatvätt hos Skatteverket med angiven anledning: Utvandrad";
									break;
								case "GN":
									p.Fritext = p.Fritext + "\r\nPerson inaktiverad vid datatvätt hos Skatteverket med angiven anledning: Gammalt personnummer";
									break;
								case "GS":
									p.Fritext = p.Fritext + "\r\nPerson inaktiverad vid datatvätt hos Skatteverket med angiven anledning: Gammalt samordningsnummer";
									break;
								case "OB":
									p.Fritext = p.Fritext + "\r\nPerson inaktiverad vid datatvätt hos Skatteverket med angiven anledning: Obefintig";
									break;
								case "TA":
								case "AS":
									p.Fritext = p.Fritext + "\r\nPerson inaktiverad vid datatvätt hos Skatteverket med angiven anledning: Tekniskt avregistrerad";
									break;
								default:
									p.Fritext = p.Fritext + "\r\nPerson inaktiverad vid datatvätt hos Skatteverket med angiven anledning: Ospecifierad anledning";
									break;
							}
							#endregion
						}

						index = post.IndexOf("#UP 01012");
						if (index != -1)
						{
							p.Fornamn = post.Substring(index + 10, post.IndexOf("\r\n", index + 1) - index - 10);
						}

						index = post.IndexOf("#UP 01014");
						if (index != -1)
						{
							p.Efternamn = post.Substring(index + 10, post.IndexOf("\r\n", index + 1) - index - 10);
						}

						index = post.IndexOf("#UP 01033");
						if (index != -1)
						{
							p.GatuAdress = post.Substring(index + 10, post.IndexOf("\r\n", index + 1) - index - 10);
						}

						index = post.IndexOf("#UP 01034");
						if (index != -1)
						{
							p.PostNr = post.Substring(index + 10, post.IndexOf("\r\n", index + 1) - index - 10);
							if (p.PostNr.Length == 5)
								p.PostNr = p.PostNr.Insert(3, " ");
						}

						index = post.IndexOf("#UP 01035");
						if (index != -1)
						{
							p.PostOrt = post.Substring(index + 10, post.IndexOf("\r\n", index + 1) - index - 10);
						}
					}
				}

				svc.UpdatePersonList(personer);
			}
		}
		#endregion

		#region E-Arkiv
		#region Helpers
		private void WriteLokal(XmlTextWriter writer, Lokal l, string year, string valtyp)
		{
			writer.WriteStartElement("IndexObject");
			XMLHelper.WriteEndLine(writer);

			XMLHelper.WriteTab(writer);
			writer.WriteStartElement("DisplayName");
			writer.WriteStartAttribute("value");
			writer.WriteString(l.ByggnadNamn + " " + l.Namn);
			writer.WriteEndAttribute();
			writer.WriteEndElement();
			XMLHelper.WriteEndLine(writer);

			XMLHelper.WriteTab(writer);
			writer.WriteStartElement("ObjectType");
			writer.WriteStartAttribute("name");
			writer.WriteString("108CE_vallokal");
			writer.WriteEndAttribute();
			writer.WriteEndElement();
			XMLHelper.WriteEndLine(writer);

			XMLHelper.WriteAttribute(writer, "original_id_definition", "Byggnad + rumsbeteckning");
			XMLHelper.WriteAttribute(writer, "title", "Lokal");
			XMLHelper.WriteAttribute(writer, "sekretess", "0");
			XMLHelper.WriteAttribute(writer, "pul", "0");
			XMLHelper.WriteAttribute(writer, "lta_system", "Kaskelot");
			XMLHelper.WriteAttribute(writer, "producer_system_version", "1.0");
			XMLHelper.WriteAttribute(writer, "startdatum", year + "-01-01");
			XMLHelper.WriteAttribute(writer, "slutdatum", year + "-12-31");
			XMLHelper.WriteAttribute(writer, "108CE_valtyp", valtyp);
			XMLHelper.WriteAttribute(writer, "108CE_valar", year);
			XMLHelper.WriteAttribute(writer, "108CE_lokaltyp", l.Byggnad.TypNamn);

			XMLHelper.WriteAttribute(writer, "108CE_lokaldistrikt", l.ValdistriktNamn);

			XMLHelper.WriteAttribute(writer, "120FF_adress", l.Byggnad.BesokAdress);
			XMLHelper.WriteAttribute(writer, "120FF_postadress", l.Byggnad.BesokPostNr + " " + l.Byggnad.BesokPostOrt);
			XMLHelper.WriteAttribute(writer, "108CE_byggnad", l.ByggnadNamn);
			XMLHelper.WriteAttribute(writer, "108CE_lokal", l.Namn);

			XMLHelper.WriteTab(writer);
			writer.WriteStartElement("Producer");
			writer.WriteStartAttribute("name");
			writer.WriteString("Valnämnden");
			writer.WriteEndAttribute();
			writer.WriteEndElement();
			XMLHelper.WriteEndLine(writer);

			XMLHelper.WriteTab(writer);
			writer.WriteStartElement("From");
			writer.WriteStartAttribute("name");
			writer.WriteString("Kaskelot");
			writer.WriteEndAttribute();
			writer.WriteEndElement();
			XMLHelper.WriteEndLine(writer);

			XMLHelper.WriteTab(writer);
			writer.WriteEndElement();
			XMLHelper.WriteEndLine(writer);
		}

		private void WriteValdistrikt(XmlTextWriter writer, Valdistrikt v, string year, string valtyp)
		{
			writer.WriteStartElement("IndexObject");
			XMLHelper.WriteEndLine(writer);

			writer.WriteStartElement("DisplayName");
			writer.WriteStartAttribute("value");
			writer.WriteString(v.ForsamlingNamn + " " + v.Forsamling.ForsamlingNr.Trim() + v.ValdistriktNr.Trim());
			writer.WriteEndAttribute();
			writer.WriteEndElement();
			XMLHelper.WriteEndLine(writer);

			writer.WriteStartElement("ObjectType");
			writer.WriteStartAttribute("name");
			writer.WriteString("108CE_valdistrikt");
			writer.WriteEndAttribute();
			writer.WriteEndElement();
			XMLHelper.WriteEndLine(writer);

			XMLHelper.WriteAttribute(writer, "original_id_definition", "Församling namn+församling nr+valdistrikt nr");
			XMLHelper.WriteAttribute(writer, "title", "Valdistrikt");
			XMLHelper.WriteAttribute(writer, "sekretess", "0");
			XMLHelper.WriteAttribute(writer, "pul", "0");
			XMLHelper.WriteAttribute(writer, "lta_system", "Kaskelot");
			XMLHelper.WriteAttribute(writer, "producer_system_version", "1.0");
			XMLHelper.WriteAttribute(writer, "startdatum", year + "-01-01");
			XMLHelper.WriteAttribute(writer, "slutdatum", year + "-12-31");
			XMLHelper.WriteAttribute(writer, "108CE_valtyp", valtyp);
			XMLHelper.WriteAttribute(writer, "108CE_valar", year);
			XMLHelper.WriteAttribute(writer, "108CE_valkrets", v.ValkretsNamn);
			XMLHelper.WriteAttribute(writer, "108CE_forsamling", v.ForsamlingNamn);
			XMLHelper.WriteAttribute(writer, "108CE_distrikt", v.ValdistriktNr);

			writer.WriteStartElement("Producer");
			writer.WriteStartAttribute("name");
			writer.WriteString("Valnämnden");
			writer.WriteEndAttribute();
			writer.WriteEndElement();
			XMLHelper.WriteEndLine(writer);

			writer.WriteStartElement("From");
			writer.WriteStartAttribute("name");
			writer.WriteString("Kaskelot");
			writer.WriteEndAttribute();
			writer.WriteEndElement();
			XMLHelper.WriteEndLine(writer);

			writer.WriteEndElement();
			XMLHelper.WriteEndLine(writer);
		}

		private void WriteValarbetare(XmlTextWriter writer, PersonData p, string year, string valtyp)
		{
			writer.WriteStartElement("IndexObject");
			XMLHelper.WriteEndLine(writer);

			writer.WriteStartElement("DisplayName");
			writer.WriteStartAttribute("value");
			writer.WriteString(p.Fornamn + " " + p.Efternamn + " " + p.Personnummer.Substring(2, 6));
			writer.WriteEndAttribute();
			writer.WriteEndElement();
			XMLHelper.WriteEndLine(writer);

			writer.WriteStartElement("ObjectType");
			writer.WriteStartAttribute("name");
			writer.WriteString("108CE_valarbetare");
			writer.WriteEndAttribute();
			writer.WriteEndElement();
			XMLHelper.WriteEndLine(writer);

			XMLHelper.WriteAttribute(writer, "original_id_definition", "Namn + födelsedatum");
			XMLHelper.WriteAttribute(writer, "title", "Valarbetare");
			XMLHelper.WriteAttribute(writer, "sekretess", p.GatuAdress.IsNullOrEmpty() ? "2" : "0");
			XMLHelper.WriteAttribute(writer, "pul", "2");
			XMLHelper.WriteAttribute(writer, "lta_system", "Kaskelot");
			XMLHelper.WriteAttribute(writer, "producer_system_version", "1.0");
			XMLHelper.WriteAttribute(writer, "startdatum", year + "-01-01");
			XMLHelper.WriteAttribute(writer, "slutdatum", year + "-12-31");
			XMLHelper.WriteAttribute(writer, "108CE_valtyp", valtyp);
			XMLHelper.WriteAttribute(writer, "108CE_valar", year);
			XMLHelper.WriteAttribute(writer, "120FF_fornamn", p.Fornamn);
			XMLHelper.WriteAttribute(writer, "120FF_efternamn", p.Efternamn);
			XMLHelper.WriteAttribute(writer, "120FF_personnummer", p.Personnummer.Substring(2, 11));
			XMLHelper.WriteAttribute(writer, "120FF_adress", p.GatuAdress);
			XMLHelper.WriteAttribute(writer, "120FF_postadress", p.PostNr + " " + p.PostOrt);
			XMLHelper.WriteAttribute(writer, "108CE_valuppdrag", p.Uppdrag);

			writer.WriteStartElement("Producer");
			writer.WriteStartAttribute("name");
			writer.WriteString("Valnämnden");
			writer.WriteEndAttribute();
			writer.WriteEndElement();
			XMLHelper.WriteEndLine(writer);

			writer.WriteStartElement("From");
			writer.WriteStartAttribute("name");
			writer.WriteString("Kaskelot");
			writer.WriteEndAttribute();
			writer.WriteEndElement();
			XMLHelper.WriteEndLine(writer);

			if (p.AnsokanPersonFornamn != null && p.AnsokanPersonEfternamn != null && p.AnsokanPersonNummer != null)
			{
				#region Ansökan
				writer.WriteStartElement("IndexDocument");
				XMLHelper.WriteEndLine(writer);

				writer.WriteStartElement("DisplayName");
				writer.WriteStartAttribute("value");
				writer.WriteString("Ansökan " + p.AnsokanPersonFornamn + " " + p.AnsokanPersonEfternamn + " " + p.Personnummer.Substring(2, 6));
				writer.WriteEndAttribute();
				writer.WriteEndElement();
				XMLHelper.WriteEndLine(writer);

				writer.WriteStartElement("ObjectType");
				writer.WriteStartAttribute("name");
				writer.WriteString("108CE_valarbetare_ansokan");
				writer.WriteEndAttribute();
				writer.WriteEndElement();
				XMLHelper.WriteEndLine(writer);

				XMLHelper.WriteAttribute(writer, "original_id_definition", "Namn + födelsedatum");
				XMLHelper.WriteAttribute(writer, "sekretess", "0");
				XMLHelper.WriteAttribute(writer, "pul", "2");
				XMLHelper.WriteAttribute(writer, "lta_system", "Kaskelot");
				XMLHelper.WriteAttribute(writer, "title", "Ansökan");
				XMLHelper.WriteAttribute(writer, "120FF_fornamn", p.AnsokanPersonFornamn);
				XMLHelper.WriteAttribute(writer, "120FF_efternamn", p.AnsokanPersonEfternamn);
				XMLHelper.WriteAttribute(writer, "108CE_personnummer", p.AnsokanPersonNummer != null ? p.AnsokanPersonNummer.Substring(2, 11) : "");
				XMLHelper.WriteAttribute(writer, "108CE_adress", p.AnsokanAdress);
				XMLHelper.WriteAttribute(writer, "108CE_postadress", p.AnsokanPostAdress);
				XMLHelper.WriteAttribute(writer, "108CE_fritext", p.AnsokanFritext);

				writer.WriteEndElement();
				XMLHelper.WriteEndLine(writer);
				#endregion
			}

			writer.WriteEndElement();
			XMLHelper.WriteEndLine(writer);
			writer.Flush();
		}
		#endregion

		private void AddLokalRegister(SPFolder folder, string filename, out string hash, out int antal, string valtyp)
		{
			MemoryStream ms = new MemoryStream();
			XmlTextWriter writer = new XmlTextWriter(ms, Encoding.Default);

			using (AdminService svc = new AdminService())
			{
				string year = ApplicationContext.Current.Val.ValDatum.HasValue ? ApplicationContext.Current.Val.ValDatum.Value.Year.ToString() : "";

				IEnumerable<Lokal> lokaler = svc.GetLokalData();
				antal = lokaler.Count();
				writer.WriteStartDocument();
				XMLHelper.WriteEndLine(writer);

				writer.WriteStartElement("lokaler");
				XMLHelper.WriteEndLine(writer);
				XMLHelper.WriteTab(writer);

				foreach (Lokal l in lokaler)
				{
					WriteLokal(writer, l, year, valtyp);
				}

				writer.WriteEndElement();
				XMLHelper.WriteEndLine(writer);

				writer.WriteEndDocument();
				writer.Flush();

				byte[] bytes = ms.GetBuffer();
				bytes = bytes.TakeWhile(x => x != 0).ToArray();

				SaveIntegration(bytes, filename, folder, out hash);
			}
		}

		private void AddValdistriktRegister(SPFolder folder, string filename, out string hash, out int antal, string valtyp)
		{
			MemoryStream ms = new MemoryStream();
			XmlTextWriter writer = new XmlTextWriter(ms, Encoding.Default);

			using (AdminService svc = new AdminService())
			{
				Val val = ApplicationContext.Current.Val;
				string year = val.ValDatum.HasValue ? val.ValDatum.Value.Year.ToString() : "";

				IEnumerable<Valdistrikt> valdistrikt = svc.GetValdistriktList(null);
				antal = valdistrikt.Count();
				writer.WriteStartDocument();
				XMLHelper.WriteEndLine(writer);

				writer.WriteStartElement("valdistrikt");
				XMLHelper.WriteEndLine(writer);
				XMLHelper.WriteTab(writer);

				foreach (Valdistrikt v in valdistrikt)
				{
					WriteValdistrikt(writer, v, year, valtyp);
				}

				writer.WriteEndElement();
				XMLHelper.WriteEndLine(writer);

				writer.WriteEndDocument();
				writer.Flush();

				byte[] bytes = ms.GetBuffer();
				bytes = bytes.TakeWhile(x => x != 0).ToArray();
				SaveIntegration(bytes, filename, folder, out hash);
			}
		}

		private void AddValarbetareRegister(SPFolder folder, string filename, out string hash, out int antal, string valtyp)
		{
			MemoryStream ms = new MemoryStream();
			XmlTextWriter writer = new XmlTextWriter(ms, Encoding.Default);

			using (AdminService svc = new AdminService())
			{
				Val val = ApplicationContext.Current.Val;
				string year = val.ValDatum.HasValue ? val.ValDatum.Value.Year.ToString() : "";

				IEnumerable<PersonData> personer = svc.GetPersonDataIntegration();
				antal = personer.Count();
				writer.WriteStartDocument();
				XMLHelper.WriteEndLine(writer);
				writer.WriteStartElement("valarbetare");
				XMLHelper.WriteEndLine(writer);
				XMLHelper.WriteTab(writer);

				foreach (PersonData p in personer)
				{
					WriteValarbetare(writer, p, year, valtyp);
				}

				writer.WriteEndElement();
				XMLHelper.WriteEndLine(writer);
				writer.WriteEndDocument();
				writer.Flush();

				byte[] bytes = ms.GetBuffer();
				bytes = bytes.TakeWhile(x => x != 0).ToArray();
				SaveIntegration(bytes, filename, folder, out hash);
			}
		}

		private void AddArkivRegister(SPFolder folder, string valtyp)
		{
			MemoryStream ms = new MemoryStream();
			XmlTextWriter writer = new XmlTextWriter(ms, Encoding.Default);
			string filename = "SIPLabel.xml";

			using (AdminService svc = new AdminService())
			{
				Val val = ApplicationContext.Current.Val;
				string year = val.ValDatum.HasValue ? val.ValDatum.Value.Year.ToString() : "";

				string lokalFilnamn = "samtliga_lokaler.xml";
				string lokalHash = string.Empty;
				int lokalAntal = 0;
				AddLokalRegister(folder, lokalFilnamn, out lokalHash, out lokalAntal, valtyp);

				string valarbetareFilnamn = "samtliga_valarbetare.xml";
				string valarbetareHash = string.Empty;
				int valarbetareAntal = 0;
				AddValarbetareRegister(folder, valarbetareFilnamn, out valarbetareHash, out valarbetareAntal, valtyp);

				string valdistriktFilnamn = "samtliga_valdistrikt.xml";
				string valdistriktHash = string.Empty;
				int valdistriktAntal = 0;
				AddValdistriktRegister(folder, valdistriktFilnamn, out valdistriktHash, out valdistriktAntal, valtyp);

				#region Document - Start
				writer.WriteStartDocument();
				XMLHelper.WriteEndLine(writer);

				writer.WriteStartElement("IndexObject");
				XMLHelper.WriteEndLine(writer);

				writer.WriteStartElement("DisplayName");
				writer.WriteStartAttribute("value");
				writer.WriteString(valtyp + (val.ValDatum.HasValue ? val.ValDatum.Value.Year.ToString() : ""));
				writer.WriteEndAttribute();
				writer.WriteEndElement();
				XMLHelper.WriteEndLine(writer);

				writer.WriteStartElement("ObjectType");
				writer.WriteStartAttribute("name");
				writer.WriteString("120FF_register");
				writer.WriteEndAttribute();
				writer.WriteEndElement();
				XMLHelper.WriteEndLine(writer);

				XMLHelper.WriteAttribute(writer, "original_id_definition", "Typ av val + år");
				XMLHelper.WriteAttribute(writer, "title", "Registerutdrag");
				XMLHelper.WriteAttribute(writer, "sekretess", "0");
				XMLHelper.WriteAttribute(writer, "pul", "0");
				XMLHelper.WriteAttribute(writer, "lta_system", "Kaskelot");
				XMLHelper.WriteAttribute(writer, "producer_system_version", "1.0");
				XMLHelper.WriteAttribute(writer, "startdatum", year + "-01-01");
				XMLHelper.WriteAttribute(writer, "slutdatum", year + "-12-31");
				XMLHelper.WriteAttribute(writer, "120FF_reg_origin", "Centralt system för valadministration. Systemet hanterar samtliga tjänstgörande valarbetare, vallokaler samt valdistrikt. Varje röstmottagare är stationerad i en lokal som ingår i ett distrikt. Systemet började användas inför det allmänna valet 2014.");
				XMLHelper.WriteAttribute(writer, "120FF_reg_content", "Tabelldata över valarbetare, vallokaler samt distrikt");

				writer.WriteStartElement("Producer");
				writer.WriteStartAttribute("name");
				writer.WriteString("Valnämnden");
				writer.WriteEndAttribute();
				writer.WriteEndElement();
				XMLHelper.WriteEndLine(writer);

				writer.WriteStartElement("From");
				writer.WriteStartAttribute("name");
				writer.WriteString("Kaskelot");
				writer.WriteEndAttribute();
				writer.WriteEndElement();
				XMLHelper.WriteEndLine(writer);
				#endregion

				#region IndexDocument - Valarbetare
				writer.WriteStartElement("IndexDocument");
				XMLHelper.WriteEndLine(writer);

				writer.WriteStartElement("DisplayName");
				writer.WriteStartAttribute("value");
				writer.WriteString("Valarbetare " + valtyp + (val.ValDatum.HasValue ? val.ValDatum.Value.Year.ToString() : ""));
				writer.WriteEndAttribute();
				writer.WriteEndElement();
				XMLHelper.WriteEndLine(writer);

				writer.WriteStartElement("ObjectType");
				writer.WriteStartAttribute("name");
				writer.WriteString("120FF_registerfil");
				writer.WriteEndAttribute();
				writer.WriteEndElement();
				XMLHelper.WriteEndLine(writer);

				XMLHelper.WriteAttribute(writer, "original_id_definition", "Namn+typ av val+år");
				XMLHelper.WriteAttribute(writer, "sekretess", "2");
				XMLHelper.WriteAttribute(writer, "pul", "2");
				XMLHelper.WriteAttribute(writer, "lta_system", "Kaskelot");
				XMLHelper.WriteAttribute(writer, "title", "Register valarbetare");
				XMLHelper.WriteAttribute(writer, "120FF_reg_file_content", "Tabell med samtliga valarbetare.");
				XMLHelper.WriteAttribute(writer, "120FF_reg_record_desc", "Xml-fil med namn på personen, typ av valarbetare, postadress, valdistrikt, vallokal, typ av val, valår.");
				XMLHelper.WriteAttribute(writer, "120FF_reg_filetype", "XML");
				XMLHelper.WriteAttribute(writer, "120FF_reg_records", valarbetareAntal.ToString());
				XMLHelper.WriteAttribute(writer, "120FF_reg_record_delim", "CR+LF");
				XMLHelper.WriteAttribute(writer, "120FF_reg_attribute_delim", "Tab");

				#region IndexFile - Samtliga Valarbetare
				writer.WriteStartElement("IndexFile");

				writer.WriteStartElement("DisplayName");
				writer.WriteStartAttribute("value");
				writer.WriteString(valarbetareFilnamn);
				writer.WriteEndAttribute();
				writer.WriteEndElement();

				XMLHelper.WriteAttribute(writer, "original_id_definition", "Filnamn");
				XMLHelper.WriteAttribute(writer, "language", "sv");
				XMLHelper.WriteAttribute(writer, "format_name", "text/xml");
				XMLHelper.WriteAttribute(writer, "lta_file_digest", "SHA1:" + valarbetareHash);

				writer.WriteEndElement();
				#endregion

				writer.WriteEndElement();
				#endregion

				#region IndexDocument - Valdistrikt
				writer.WriteStartElement("IndexDocument");
				XMLHelper.WriteEndLine(writer);

				writer.WriteStartElement("DisplayName");
				writer.WriteStartAttribute("value");
				writer.WriteString("Valdistrikt " + valtyp + (val.ValDatum.HasValue ? val.ValDatum.Value.Year.ToString() : ""));
				writer.WriteEndAttribute();
				writer.WriteEndElement();
				XMLHelper.WriteEndLine(writer);

				writer.WriteStartElement("ObjectType");
				writer.WriteStartAttribute("name");
				writer.WriteString("120FF_registerfil");
				writer.WriteEndAttribute();
				writer.WriteEndElement();
				XMLHelper.WriteEndLine(writer);

				XMLHelper.WriteAttribute(writer, "original_id_definition", "Namn+typ av val+år");
				XMLHelper.WriteAttribute(writer, "sekretess", "0");
				XMLHelper.WriteAttribute(writer, "pul", "0");
				XMLHelper.WriteAttribute(writer, "lta_system", "Kaskelot");
				XMLHelper.WriteAttribute(writer, "title", "Register valdistrikt");
				XMLHelper.WriteAttribute(writer, "120FF_reg_file_content", "Tabell med samtliga Stockholms stads valdistrikt.");
				XMLHelper.WriteAttribute(writer, "120FF_reg_record_desc", "Xml-fil med namn på valkrets, församling och valdistritet.");
				XMLHelper.WriteAttribute(writer, "120FF_reg_filetype", "XML");
				XMLHelper.WriteAttribute(writer, "120FF_reg_records", valdistriktAntal.ToString());
				XMLHelper.WriteAttribute(writer, "120FF_reg_record_delim", "CR+LF");
				XMLHelper.WriteAttribute(writer, "120FF_reg_attribute_delim", "Tab");

				#region IndexFile - Samtliga Valdistrikt
				writer.WriteStartElement("IndexFile");

				writer.WriteStartElement("DisplayName");
				writer.WriteStartAttribute("value");
				writer.WriteString(valdistriktFilnamn);
				writer.WriteEndAttribute();
				writer.WriteEndElement();

				XMLHelper.WriteAttribute(writer, "original_id_definition", "Filnamn");
				XMLHelper.WriteAttribute(writer, "language", "sv");
				XMLHelper.WriteAttribute(writer, "format_name", "text/xml");
				XMLHelper.WriteAttribute(writer, "lta_file_digest", "SHA1:" + valdistriktHash);

				writer.WriteEndElement();
				#endregion

				writer.WriteEndElement();
				XMLHelper.WriteEndLine(writer);
				#endregion

				#region IndexDocument - Vallokaler
				writer.WriteStartElement("IndexDocument");
				XMLHelper.WriteEndLine(writer);

				writer.WriteStartElement("DisplayName");
				writer.WriteStartAttribute("value");
				writer.WriteString("Vallokaler " + valtyp + (val.ValDatum.HasValue ? val.ValDatum.Value.Year.ToString() : ""));
				writer.WriteEndAttribute();
				writer.WriteEndElement();
				XMLHelper.WriteEndLine(writer);

				writer.WriteStartElement("ObjectType");
				writer.WriteStartAttribute("name");
				writer.WriteString("120FF_registerfil");
				writer.WriteEndAttribute();
				writer.WriteEndElement();
				XMLHelper.WriteEndLine(writer);

				XMLHelper.WriteAttribute(writer, "original_id_definition", "Namn+typ av val+år");
				XMLHelper.WriteAttribute(writer, "sekretess", "0");
				XMLHelper.WriteAttribute(writer, "pul", "0");
				XMLHelper.WriteAttribute(writer, "lta_system", "Kaskelot");
				XMLHelper.WriteAttribute(writer, "title", "Register vallokaler");
				XMLHelper.WriteAttribute(writer, "120FF_reg_file_content", "Tabell med samtliga lokaler i Stockholms stad.");
				XMLHelper.WriteAttribute(writer, "120FF_reg_record_desc", "Xml-fil med namn på lokalen, namn på byggnaden, typ av lokal.");
				XMLHelper.WriteAttribute(writer, "120FF_reg_filetype", "XML");
				XMLHelper.WriteAttribute(writer, "120FF_reg_records", lokalAntal.ToString());
				XMLHelper.WriteAttribute(writer, "120FF_reg_record_delim", "CR+LF");
				XMLHelper.WriteAttribute(writer, "120FF_reg_attribute_delim", "Tab");

				#region IndexFile - Samtliga Vallokaler
				writer.WriteStartElement("IndexFile");

				writer.WriteStartElement("DisplayName");
				writer.WriteStartAttribute("value");
				writer.WriteString(lokalFilnamn);
				writer.WriteEndAttribute();
				writer.WriteEndElement();

				XMLHelper.WriteAttribute(writer, "original_id_definition", "Filnamn");
				XMLHelper.WriteAttribute(writer, "language", "sv");
				XMLHelper.WriteAttribute(writer, "format_name", "text/xml");
				XMLHelper.WriteAttribute(writer, "lta_file_digest", "SHA1:" + lokalHash);

				writer.WriteEndElement();
				#endregion

				writer.WriteEndElement();
				XMLHelper.WriteEndLine(writer);
				#endregion

				#region Document - End
				writer.WriteEndElement();
				XMLHelper.WriteEndLine(writer);
				writer.WriteEndDocument();
				writer.Flush();
				#endregion

				byte[] bytes = ms.GetBuffer();
				bytes = bytes.TakeWhile(x => x != 0).ToArray();

				SaveIntegration(bytes, filename, folder);
			}
		}

		private void AddArkivVallokaler(SPFolder folder, string valtyp)
		{
			using (AdminService svc = new AdminService())
			{
				Val val = ApplicationContext.Current.Val;
				string year = val.ValDatum.HasValue ? val.ValDatum.Value.Year.ToString() : "";

				IList<Lokal> lokaler = svc.GetLokalData().ToList();

				for (int i = 0; i < lokaler.Count(); i++)
				{
					SPFolder subfolder = folder.SubFolders.Add("Lokal" + (i + 1));

					MemoryStream ms = new MemoryStream();
					XmlTextWriter writer = new XmlTextWriter(ms, Encoding.Default);
					writer.WriteStartDocument();
					XMLHelper.WriteEndLine(writer);

					WriteLokal(writer, lokaler[i], year, valtyp);

					writer.WriteEndDocument();
					writer.Flush();

					byte[] bytes = ms.GetBuffer();
					bytes = bytes.TakeWhile(x => x != 0).ToArray();
					SaveIntegration(bytes, "SIPLabel.xml", subfolder);
				}
			}
		}

		private void AddArkivValdistrikt(SPFolder folder, string valtyp)
		{
			using (AdminService svc = new AdminService())
			{
				Val val = ApplicationContext.Current.Val;
				string year = val.ValDatum.HasValue ? val.ValDatum.Value.Year.ToString() : "";

				IList<Valdistrikt> valdistrikt = svc.GetValdistriktList(null);

				for (int i = 0; i < valdistrikt.Count(); i++)
				{
					SPFolder subfolder = folder.SubFolders.Add("Valdistrikt" + (i + 1));

					MemoryStream ms = new MemoryStream();
					XmlTextWriter writer = new XmlTextWriter(ms, Encoding.Default);
					writer.WriteStartDocument();
					XMLHelper.WriteEndLine(writer);

					WriteValdistrikt(writer, valdistrikt[i], year, valtyp);

					writer.WriteEndDocument();
					writer.Flush();

					byte[] bytes = ms.GetBuffer();
					bytes = bytes.TakeWhile(x => x != 0).ToArray();
					SaveIntegration(bytes, "SIPLabel.xml", subfolder);
				}
			}
		}

		private void AddArkivValarbetare(SPFolder folder, string valtyp)
		{
			using (AdminService svc = new AdminService())
			{
				Val val = ApplicationContext.Current.Val;
				string year = val.ValDatum.HasValue ? val.ValDatum.Value.Year.ToString() : "";

				IList<PersonData> personer = svc.GetPersonDataIntegration().ToList();

				for (int i = 0; i < personer.Count(); i++)
				{
					SPFolder subfolder = folder.SubFolders.Add("Person" + (i + 1));

					MemoryStream ms = new MemoryStream();
					XmlTextWriter writer = new XmlTextWriter(ms, Encoding.Default);
					writer.WriteStartDocument();
					XMLHelper.WriteEndLine(writer);

					WriteValarbetare(writer, personer[i], year, valtyp);

					writer.WriteEndDocument();
					writer.Flush();

					byte[] bytes = ms.GetBuffer();
					bytes = bytes.TakeWhile(x => x != 0).ToArray();
					SaveIntegration(bytes, "SIPLabel.xml", subfolder);
				}
			}
		}

		public string CreateArkiv(string valtyp)
		{
			string url = null;
			Guid siteId = SPContext.Current.Site.ID;

			SPSecurity.RunWithElevatedPrivileges(delegate()
			{
				using (SPSite site = new SPSite(siteId))
				{
					bool oldAllowUnsafeUpdates = site.RootWeb.AllowUnsafeUpdates;
					try
					{
						site.RootWeb.AllowUnsafeUpdates = true;

						SPFolder folder = new DocumentService().GetEArkivFolder(site);

						AddArkivRegister(folder.SubFolders.Add("Register"), valtyp);
						AddArkivValarbetare(folder.SubFolders.Add("Valarbetare"), valtyp);
						AddArkivValdistrikt(folder.SubFolders.Add("Valdistrikt"), valtyp);
						AddArkivVallokaler(folder.SubFolders.Add("Vallokaler"), valtyp);

						Stream zipStream = ZipFolder(folder);

						SPFile file = folder.ParentFolder.Files.Add("eArkiv.zip", zipStream, true);

						url = file.Url;
					}
					finally
					{
						site.RootWeb.AllowUnsafeUpdates = oldAllowUnsafeUpdates;
					}
				}
			});

			return url;
		}
		#endregion
	}
}
